using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.ComponentModel; using System.Collections.Specialized; using miew.Lambda; using miew.Mesh; using miew.Enumerable; namespace agree.Wpf.Util { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class DagLayoutPanel : Panel { LayoutDag _dag; RailSet rails; public DagLayoutPanel() { _dag = new LayoutDag(this); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override void OnChildDesiredSizeChanged(UIElement child) { base.OnChildDesiredSizeChanged(child); #if true foreach (LayoutDag.Node node in _dag) { node.ReMeasure(); } rails = new RailSet(_dag); InvalidateArrange(); #else FrameworkElement fe = child as FrameworkElement; if (fe != null && _dag.ReMeasureChild(fe)) { InvalidateArrange(); } #endif } public void FOO() { foreach (LayoutDag.Node node in _dag) { node.ReMeasure(); } rails = new RailSet(_dag); InvalidateArrange(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) { base.OnVisualChildrenChanged(visualAdded, visualRemoved); FrameworkElement fe_add = visualAdded as FrameworkElement; if (fe_add != null && !_dag.Contains(fe_add)) _dag.AddChild(fe_add); FrameworkElement fe_sub = visualRemoved as FrameworkElement; if (fe_sub != null && _dag.Contains(fe_sub)) _dag.RemoveChild(fe_sub); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void ChangeNodeParents(FrameworkElement fe, IList old_list, IList new_list) { if (fe.Parent != this) throw new Exception(); if (!_dag.ChangeNodeParents(fe, new_list.OfType<FrameworkElement>())) return; InvalidateArrange(); InvalidateVisual(); #if false var inpc_new = new_list as INotifyCollectionChanged; if (inpc_new != null) inpc_new.CollectionChanged += (o, e) => { Debugger.Break(); }; var inpc_old = old_list as INotifyCollectionChanged; if (inpc_old != null) inpc_old.CollectionChanged -= h; #endif } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override Size MeasureOverride(Size availableSize) { if (_dag.Count == 0) return new Size(100, 100); rails = new RailSet(_dag); foreach (Rail r in rails) { //r.OnDagLoaded(); //if (r.Count > 2) // r.bvHorzPad.SetValue((max_width - r.Width) / (r.Count - 1)); //else //r.left_start.SetValue(max_width / 2 - r.Width / 2); } #if false //for (int j = 0; j < 15; j++) { //Debug.Print("================"); int cmov = 0; int pmov = 0; foreach (LayoutDag.Node node in _dag) { int child_lev = node.Level + 1; ; if (node.Children.Count > 0 && node.Children.All(c => c.Level == child_lev && c.Parents.Count == 1)) { Rail cr = rails[child_lev]; var rgch = node.Children/*.OrderByDescending(ch => ch.AllDescendants.Count)*/.ToArray(); /// don't bother grouping children if all children on this level are included if (rgch.Length != cr.Count) { double wa = rgch.WeightedAverage(n => n.railpos.RailCalcs().Center.Value, n => n.AllDescendants.Count); // find a starting index for the first child int new_ix = cr.FindIndex(wa); foreach (var n in rgch) { Rail.SingleNodePos rp_old = n.railpos; if (rp_old.ItemIndex != new_ix) { // Debug.Print("child: rail {0}: ix{1} -> ix{2}", child_lev, rp_old.RailIndex, new_ix); //rp_old.Min = null; //rp_old.Extra = null; rp_old.MoveTo(ref new_ix); cmov++; } new_ix++; } double dx = rgch[rgch.Length - 1].railpos.RailCalcs().Right.Value - rgch[0].railpos.RailCalcs().Left.Value; double dxx = rgch[0].railpos.RailCalcs().Left.Value + (dx / 2); int zz = rails[node.Level].FindIndex(dxx); if (zz != node.railpos.ItemIndex) { //Debug.Print("parent: rail {0}: ix{1} -> ix{2}", node.Level, node.railpos.RailIndex, zz); node.railpos.MoveTo(ref zz); pmov++; } //node.railpos.Min = rgch[0].railpos.Left; //node.railpos.Extra = new BvdCenterNode(rgch[0].railpos.Left, rgch[rgch.Length - 1].railpos.Right, node.railpos.Width); //foreach (LayoutDag.Node n in dag) //{ // children moved to consecutive on rail // first child : max (rail position, // parent-left determined by children //} } } } //Debug.Print("cmov: {0} pmov: {1}", cmov, pmov); } #endif double x_min = _dag.Min(n => n.Final.Left); double x_max = _dag.Max(n => n.Final.Right); double y_max = _dag.Max(n => n.Final.Bottom); double xdx = x_max - x_min; RenderTransform = new TranslateTransform(-x_min, 0); return new Size(xdx, y_max); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override Size ArrangeOverride(Size finalSize) { if (_dag.Count == 0) return finalSize; bool f_any = false; foreach (var li in _dag) { Debug.Assert(VisualTreeHelper.GetParent(li.Item) == this); Vector v = VisualTreeHelper.GetOffset(li.Item); Rect f = li.Final; if (f.Left != v.X || f.Top != v.Y || f.Width != li.Item.ActualWidth || f.Height != li.Item.ActualHeight) { li.Item.Arrange(li.Final); f_any = true; } #if true Grid g = new Grid(); g.ColumnDefinitions.Add(new ColumnDefinition()); g.ColumnDefinitions.Add(new ColumnDefinition()); g.ColumnDefinitions.Add(new ColumnDefinition()); int row = 0; foreach (String x in li.railpos.ToString().Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) { String[] rg2 = x.Split(new Char[] { ':', ' ' }, StringSplitOptions.RemoveEmptyEntries); g.RowDefinitions.Add(new RowDefinition()); g.Children.Add(Anon<TextBlock>.New(tb => { tb.Text = rg2[0]; tb.Margin = new Thickness(2, 0, 2, 0); Grid.SetColumn(tb, 0); Grid.SetRow(tb, row); })); if (rg2.Length > 1) g.Children.Add(Anon<TextBlock>.New(tb => { tb.Text = rg2[1]; tb.Margin = new Thickness(2, 0, 2, 0); tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Right; Grid.SetColumn(tb, 1); Grid.SetRow(tb, row); })); if (rg2.Length > 2) g.Children.Add(Anon<TextBlock>.New(tb => { tb.Text = rg2[2]; tb.Margin = new Thickness(2, 0, 2, 0); tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Right; Grid.SetColumn(tb, 2); Grid.SetRow(tb, row); })); row++; } li.Item.ToolTip = g; li.Item.SetValue(ToolTipService.InitialShowDelayProperty, 0); li.Item.SetValue(ToolTipService.ShowDurationProperty, 360000); #endif } if (f_any) InvalidateVisual(); return finalSize; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override void OnRender(DrawingContext dc) { base.OnRender(dc); if (_dag == null) return; Pen pen = new Pen(Stroke, StrokeThickness); Pen dashpen = new Pen(Stroke, StrokeThickness); dashpen.DashStyle = DashStyles.Dash; foreach (var li in _dag) { li.DoRender(dc, pen, dashpen); } } }; }